using DG.Tweening;
using DTFramework.Util;
using System;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;

namespace DTFramework
{
    [RequireComponent(typeof(Camera))]
    public class CameraController : MonoBehaviour, ICameraControl
    {
        [Header("目标相机")]
        public Camera m_Camera;
        [Header("锁住相机")]
        public bool m_IsLockCamera = false;
        [Header("移动、旋转和缩放 速度")]
        public float m_MoveSpeed = 0.06f;
        public float m_RotateSpeed = 0.3f;
        public float m_ScaleSpeed = 10f;
        public float m_KeyboardSpeed = 10f;

        [Header("限制高度  旋转角度")]
        public float m_MinHeight = 7f;
        public float m_MaxHeight = 300f;
        public float m_MinAngle = 12f;
        public float m_MaxAngle = 80f;

        [Header("阻尼速度")]
        public float m_DeltaTimeSpeed = 13f;
        [Header("其他")]
        [Tooltip("根据相机到地面距离，动态调整各个值系数，做适配")]
        public float m_CameraDistanceDynamicValue = 0.5f;
        [Tooltip("旋转时，缺少射线检测的中心点最远距离")]
        public float m_RotateNotRayMaxDistance = 100f;
        public bool m_IsCloudRender = false;
        public bool m_IsCheckMaskUI = true;

        #region 私有变量
        private InputManager _inputManager;

        private Transform _cameraChild, _cameraTargetTrans;
        private Vector3 _mouseStartPos, _mousePos;
        private Vector3 _rotateCenter;
        private Vector3 _tempCameraTargetPos;
        private Quaternion _tempCameraTargetAngle;
        private int _scaleDirect;
        //当前看向的位置
        private Vector3 _curtargetLookPos, _curtargetAngle;

        #endregion

        public bool IsLockCamera { get => m_IsLockCamera; set => m_IsLockCamera = value; }
        public Camera CameraUtil => m_Camera;
        public InputManager InputManager => _inputManager;

        /// <summary>
        /// 相机发生变化  参数：1：移动；2：旋转；3：缩放；4：键盘控制；5：镜头控制
        /// </summary>
        public event Action<Movement> OnChanged;

        private void Awake()
        {
            GameEntry.CameraControl = this;

            if (m_Camera == null) m_Camera = GetComponent<Camera>();

            _inputManager = new InputManager();

            _cameraTargetTrans = new GameObject("CameraTargetTrans").transform;
            _cameraChild = CreateCameraChild();

            if (!EventSystem.current)
            {
                GameObject obj = new GameObject("EventSystem");
                obj.AddComponent<EventSystem>();
                obj.AddComponent<StandaloneInputModule>();
            }
        }

        private void OnEnable()
        {
            _inputManager.Enable();
        }
        // Start is called before the first frame update
        void Start()
        {
            _scaleDirect = m_IsCloudRender ? -1 : 1;

            ResetCameraTargetTransform();
            //鼠标控制： 移动、旋转、缩放事件
            _inputManager.CameraControl.Mouse_Move.started += Move_started;
            _inputManager.CameraControl.Mouse_Rotate.started += OnRotate_started;
            _inputManager.CameraControl.Mouse_Scale.started += Scale_started;
            _inputManager.CameraControl.Mouse_Scale.performed += Scale_performed;
            //键盘控制
            _inputManager.CameraControl.Keyboard_WASD.started += Movement_started;
            _inputManager.CameraControl.Keyboard_QE.started += QE_started;
        }

        #region 移动、旋转、缩放事件实现方法
        private void Move_started(InputAction.CallbackContext callback)
        {
            _mouseStartPos = Mouse.current.position.ReadValue();
            ResetCameraTargetTransform();
        }
        private void OnRotate_started(InputAction.CallbackContext obj)
        {
            _mouseStartPos = Mouse.current.position.ReadValue();
            _rotateCenter = GetRotateAroundCenter();
            ResetCameraTargetTransform();
        }
        private void Scale_started(InputAction.CallbackContext obj)
        {
            _mouseStartPos = Mouse.current.position.ReadValue();
            ResetCameraTargetTransform();
        }
        private void Scale_performed(InputAction.CallbackContext context)
        {
            var scroll = context.ReadValue<float>();
            ScaleDetectorForUpdate(scroll);
        }
        private void Movement_started(InputAction.CallbackContext context)
        {
            _mouseStartPos = Mouse.current.position.ReadValue();
            ResetCameraTargetTransform();
        }
        private void QE_started(InputAction.CallbackContext context)
        {
            _mouseStartPos = Mouse.current.position.ReadValue();
            ResetCameraTargetTransform();
        }
        #endregion

        // Update is called once per frame
        void Update()
        {
            if (m_IsLockCamera) return;

            if (m_IsCheckMaskUI)
            {
                if (UIRaycastUtil.IsPointerOverMaskUI("MaskUI")) return;
            }
            _mousePos = Mouse.current.position.ReadValue();
            if (_mousePos.x < 0 || _mousePos.x > Screen.width || _mousePos.y < 0 || _mousePos.y > Screen.height)
                return;

            if (_inputManager.CameraControl.Mouse_Move.IsPressed())
            {
                MoveDetectorForUpdate(_mousePos);
            }

            if (_inputManager.CameraControl.Mouse_Rotate.IsPressed())
            {
                RotateDetectorForUpdate(_mousePos);
            }
            if (_inputManager.CameraControl.Keyboard_WASD.IsPressed())
            {
                var moveValue = _inputManager.CameraControl.Keyboard_WASD.ReadValue<Vector2>();
                KeyboardWASDDetectorForUpdate(moveValue);
            }
            if (_inputManager.CameraControl.Keyboard_QE.IsPressed())
            {
                var moveValue = _inputManager.CameraControl.Keyboard_QE.ReadValue<float>();
                KeyboardQEDetectorForUpdate(moveValue);
            }

            m_Camera.transform.position = Vector3.Lerp(m_Camera.transform.position, _cameraTargetTrans.position, Time.deltaTime * m_DeltaTimeSpeed);
            m_Camera.transform.rotation = Quaternion.Lerp(m_Camera.transform.rotation, _cameraTargetTrans.rotation, Time.deltaTime * m_DeltaTimeSpeed);
        }

        private void OnDisable()
        {
            _inputManager.Disable();
        }
        #region 操作、控制 相机
        private void MoveDetectorForUpdate(Vector3 screenPos)
        {
            var deltaPos = screenPos - _mouseStartPos;
            if (deltaPos.sqrMagnitude <= 0.1) return;
            //相机位置的偏移量（Vector3类型，实现原理是：向量的加法）
            Vector3 moveDir = (deltaPos.x * -_cameraTargetTrans.transform.right + deltaPos.y * -_cameraTargetTrans.transform.forward);
            //限制y轴的偏移量
            moveDir.y = 0;
            _cameraTargetTrans.position += moveDir * m_MoveSpeed * (_cameraTargetTrans.position.y / (m_MaxHeight - 100));
            _mouseStartPos = screenPos;
            //检查旋转角度
            CheckRotateAngleRange();
            //检查移动高度
            CheckMoveRange();

            OnChanged?.Invoke(Movement.move);
        }
        private void RotateDetectorForUpdate(Vector3 screenPos)
        {
            var deltaPos = screenPos - _mouseStartPos;
            if (deltaPos.sqrMagnitude <= 0.1f) return;
            var normalized = deltaPos.normalized;
            if (Mathf.Abs(normalized.y) >= Mathf.Abs(normalized.x) && Mathf.Abs(normalized.y) > 0.8f)
            {
                _cameraTargetTrans.RotateAround(_rotateCenter, _cameraTargetTrans.right, -deltaPos.y * m_RotateSpeed * 0.35f);
            }
            else if (Mathf.Abs(normalized.x) > Mathf.Abs(normalized.y) && Mathf.Abs(normalized.x) > 0.8f)
            {
                _cameraTargetTrans.RotateAround(_rotateCenter, Vector3.up, deltaPos.x * m_RotateSpeed);
            }
            _mouseStartPos = screenPos;
            //检查旋转角度
            CheckRotateAngleRange();
            //检查移动高度
            CheckMoveRange();

            OnChanged?.Invoke(Movement.rotate);
        }
        private void ScaleDetectorForUpdate(float scrollWheel)
        {
            if (scrollWheel == 0.0f) return;

            _cameraTargetTrans.Translate(Vector3.forward * scrollWheel * m_ScaleSpeed * _scaleDirect, _cameraChild);

            //检查移动高度
            CheckMoveRange();

            OnChanged?.Invoke(Movement.scale);
        }

        private void KeyboardWASDDetectorForUpdate(Vector2 moveValue)
        {
            //相机位置的偏移量
            Vector3 moveDir = (moveValue.x * _cameraTargetTrans.transform.right * m_KeyboardSpeed + moveValue.y * _cameraTargetTrans.transform.forward * m_KeyboardSpeed);
            //限制y轴的偏移量
            moveDir.y = 0;
            _cameraTargetTrans.position += moveDir * m_MoveSpeed * (_cameraTargetTrans.position.y / (m_MaxHeight - 100));
            //检查移动高度
            CheckMoveRange();

            OnChanged?.Invoke(Movement.keyboard);
        }
        private void KeyboardQEDetectorForUpdate(float moveValue)
        {
            if (moveValue == 0) return;

            // _cameraTargetTrans.Translate(Vector3.forward * moveValue * m_ScaleSpeed * _scaleDirect * m_KeyboardSpeed * 0.01f, _cameraChild);
            _cameraTargetTrans.Translate(Vector3.up * moveValue * m_ScaleSpeed  * m_KeyboardSpeed * 0.01f, _cameraChild);
            //检查移动高度
            CheckMoveRange();

            OnChanged?.Invoke(Movement.keyboard);
        }
        #endregion

        private void CheckMoveRange()
        {
            var height = _cameraTargetTrans.position.y;

            if (height < m_MinHeight || height > m_MaxHeight)
            {
                height = height < m_MinHeight ? m_MinHeight + 1 : m_MaxHeight - 1;
                _tempCameraTargetPos = new Vector3(_tempCameraTargetPos.x, height, _tempCameraTargetPos.z);
                _cameraTargetTrans.rotation = _tempCameraTargetAngle;
                _cameraTargetTrans.position = _tempCameraTargetPos;
            }
            else
            {
                _tempCameraTargetPos = _cameraTargetTrans.position;
                _tempCameraTargetAngle = _cameraTargetTrans.rotation;
            }
        }

        private void CheckRotateAngleRange()
        {
            var angle = _cameraTargetTrans.eulerAngles.x;

            if (angle < m_MinAngle || angle > m_MaxAngle)
            {
                angle = angle < m_MinAngle ? m_MinAngle + 1 : m_MaxAngle - 1;
                _tempCameraTargetAngle = Quaternion.Euler(angle, _tempCameraTargetAngle.eulerAngles.y, _tempCameraTargetAngle.eulerAngles.z);
                _cameraTargetTrans.rotation = _tempCameraTargetAngle;
                _cameraTargetTrans.position = _tempCameraTargetPos;

            }
            else
            {
                _tempCameraTargetPos = _cameraTargetTrans.position;
                _tempCameraTargetAngle = _cameraTargetTrans.rotation;
            }
        }
        private void CheckMoveAndRotateViewRange()
        {
            var height = m_Camera.transform.position.y;
            var angle = m_Camera.transform.eulerAngles.x;

            if (height < m_MinHeight || height > m_MaxHeight)
            {
                height = height < m_MinHeight ? m_MinHeight + 1 : m_MaxHeight - 1;
                var targetPos = new Vector3(m_Camera.transform.position.x, height, m_Camera.transform.position.z);
                m_Camera.transform.position = targetPos;
            }
            if (angle < m_MinAngle || angle > m_MaxAngle)
            {
                angle = angle < m_MinAngle ? m_MinAngle + 1 : m_MaxAngle - 1;
                var targetAngle = Quaternion.Euler(angle, m_Camera.transform.eulerAngles.y, m_Camera.transform.eulerAngles.z);
                m_Camera.transform.rotation = targetAngle;
            }
        }

        private Transform CreateCameraChild()
        {
            //创建子对象
            var child = new GameObject("ChildObj").transform;
            child.parent = m_Camera.transform;
            child.localPosition = Vector3.zero;
            child.localEulerAngles = Vector3.zero;
            child.localScale = Vector3.one;
            return child;
        }
        private void ResetCameraTargetTransform()
        {
            _cameraTargetTrans.position = m_Camera.transform.position;
            _cameraTargetTrans.rotation = m_Camera.transform.rotation;
        }

        /// <summary>
        /// 获取摄像机中心点射线打到的位置
        /// </summary>
        /// <returns></returns>
        private Vector3 GetRotateAroundCenter()
        {
            Ray ray = m_Camera.ViewportPointToRay(Vector2.one * 0.5f);
            if (Physics.Raycast(ray, out RaycastHit hit, 500f))
            {
                return hit.point;
            }
            var camPos = m_Camera.transform.position;
            camPos += m_Camera.transform.forward * m_RotateNotRayMaxDistance;
            return new Vector3(camPos.x, 0, camPos.z);
        }

        #region 镜头跳转动画 Tween
        public void MoveRotateLookToTarget(Vector3 targetLookPos, float distance, UnityAction callback)
        {
            var tween1 = m_Camera.transform.DOLookAt(targetLookPos, 0.48f);
            var targetPos = targetLookPos - (targetLookPos - m_Camera.transform.position).normalized * distance;
            //位置点偏移
            var tween2 = m_Camera.transform.DOMove(targetPos, 0.72f);
            DOTween
                .Sequence()
                .PrependCallback(() => m_IsLockCamera = true)
                .Append(tween1)
                .Join(tween2)
                .SetEase(Ease.Linear)
                .OnComplete(() =>
                {
                    callback?.Invoke();
                    m_IsLockCamera = false;
                    CheckMoveAndRotateViewRange();
                    ResetCameraTargetTransform();
                })
                .SetAutoKill();
        }
        public void MoveRotateToTarget(Vector3 targetPos, Vector3 targetAngle, bool isRepeat, UnityAction callback)
        {
            float time = 1;
            if (!isRepeat)
            {
                if (_curtargetLookPos == targetPos && _curtargetAngle == targetAngle)
                {
                    callback?.Invoke();
                    return;
                }
            }
            var tween1 = m_Camera.transform.DOMove(targetPos, time);
            var tween2 = m_Camera.transform.DORotate(targetAngle, time);
            DOTween
              .Sequence()
              .PrependCallback(() => m_IsLockCamera = true)
              .Append(tween1)
              .Join(tween2)
              .OnComplete(() =>
              {
                  callback?.Invoke();
                  m_IsLockCamera = false;

                  CheckMoveAndRotateViewRange();
                  ResetCameraTargetTransform();
              })
              .SetAutoKill();

            _curtargetLookPos = targetPos;
            _curtargetAngle = targetAngle;
        }
        public void MoveRotateLookToTarget(Vector3 targetLookPos, float time = 1, float distance = 40, UnityAction callback = null)
        {
            if (_curtargetLookPos == targetLookPos)
            {
                callback?.Invoke();
                return;
            }
            var tween1 = m_Camera.transform.DOLookAt(targetLookPos, 0.48f);
            var targetPos = targetLookPos - (targetLookPos - m_Camera.transform.position).normalized * distance;
            targetPos = new Vector3(targetPos.x, Mathf.Clamp(targetPos.y, 50, 1000), targetPos.z);
            var tween2 = m_Camera.transform.DOMove(targetPos, 0.72f);
            DOTween
                .Sequence()
                .PrependCallback(() => m_IsLockCamera = true)
                .Append(tween1)
                .Join(tween2)
                .SetEase(Ease.Linear)
                .OnComplete(() =>
                {
                    callback?.Invoke();
                    m_IsLockCamera = false;
                    CheckMoveAndRotateViewRange();
                    ResetCameraTargetTransform();
                })
                .SetAutoKill();

            _curtargetLookPos = targetLookPos;
        }


        #endregion

    }

}